﻿// <copyright file="EntityFrameworkModelTemplate.cs" company="T4 Toolbox Team">
//  Copyright © T4 Toolbox Team. All Rights Reserved.
// </copyright>

namespace T4Toolbox.EntityFramework
{
    using System;
    using System.Collections.Generic;
    using System.Data.Metadata.Edm;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Xml;

    /// <summary>
    /// Base class for Entity Framework code generation templates.
    /// </summary>
    public abstract class EntityFrameworkModelTemplate : Template
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="EntityFrameworkModelTemplate"/> class.
        /// </summary>
        /// <remarks>
        /// Changes default output encoding to UTF-8.
        /// </remarks>
        protected EntityFrameworkModelTemplate()
        {
            this.Output.Encoding = System.Text.Encoding.UTF8;
            this.Output.BuildAction = BuildAction.EmbeddedResource;
        }

        /// <summary>
        /// Represents a method that generates XML.
        /// </summary>
        /// <param name="xmlWriter">
        /// An <see cref="XmlWriter"/> object.
        /// </param>
        /// <seealso cref="WriteXml"/>
        protected delegate void WriteXmlMethod(XmlWriter xmlWriter);

        /// <summary>
        /// Overrides the base method to set the LogicalName build property for the 
        /// output file and exclude namespace from the resource name.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> that contains the event data. 
        /// </param>
        protected override void OnRendering(EventArgs e)
        {
            base.OnRendering(e);
            this.Output.BuildProperties["LogicalName"] = Path.GetFileName(this.Output.File);
        }

        /// <summary>
        /// Writes XML to template output.
        /// </summary>
        /// <param name="method">
        /// A delegate that encapsulates a method that generates XML.
        /// </param>
        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "We don't dispose streamWriter and streamReader so that memoryStream is not closed twice")]
        protected void WriteXml(WriteXmlMethod method)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            using (MemoryStream memoryStream = new MemoryStream())
            {
                StreamWriter streamWriter = new StreamWriter(memoryStream, this.Output.Encoding);
                using (XmlWriter xmlWriter = XmlWriter.Create(streamWriter, new XmlWriterSettings() { Indent = true, CloseOutput = false }))
                {
                    method(xmlWriter);
                }

                memoryStream.Seek(0, SeekOrigin.Begin);
                StreamReader streamReader = new StreamReader(memoryStream, this.Output.Encoding);
                string xml = streamReader.ReadToEnd();
                this.Write(xml);
            }
        }
    }
}
